package com.demo.user.exception;

import com.demo.user.validation.ValidationResultDto;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;

/**
 * @author xiexiaohu
 */
@Service
public class BeanValidatorExceptionHandler extends AbstractExceptionHandler {

    /**
     *
     * Description: set the validation data.
     *
     */
    @Override
    protected void setValidationErrorData(final Throwable ex, final Object handler, final String formId,
        List<ValidationResultDto> errorData) {
        ConstraintViolationException vex = (ConstraintViolationException) ex;
        Set<ConstraintViolation<?>> constraintsViolatioins = vex.getConstraintViolations();
        if (constraintsViolatioins != null && constraintsViolatioins.size() > 0
                && handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            // method parameter arrays
            MethodParameter[] methodParameters = handlerMethod.getMethodParameters();
            if (methodParameters != null && methodParameters.length > 0
                    && !Constant.MANUAL_VALIDATE.equals(vex.getMessage())) {
                for (ConstraintViolation<?> constraintViolation : constraintsViolatioins) {
                    Class<?> doaminClass = constraintViolation.getRootBeanClass();
                    for (MethodParameter methodParameter : methodParameters) {
                        Class<?> dtoClass = methodParameter.getParameterType();
                        if (doaminClass.equals(dtoClass)) {
                            setResultDto(constraintViolation, errorData, formId, false);
                        }
                    }
                }
            } else {
                for (ConstraintViolation<?> constraintViolation : constraintsViolatioins) {
                    setResultDto(constraintViolation, errorData, formId, true);
                }
            }
        }
    }

    /**
     *
     * Description: set the result dto
     *
     * @param constraintViolation
     * @throws NoSuchFieldException
     */
    private void setResultDto(ConstraintViolation<?> constraintViolation, List<ValidationResultDto> errorData,
            String formId, boolean notManually) {
        final String beanName = constraintViolation.getRootBeanClass().getName();
        final String errorMessage = constraintViolation.getMessage();
        final String fieldName = constraintViolation.getPropertyPath().toString();
        Class<?> rootClass = constraintViolation.getRootBeanClass();
        setFieldErrorMap(fieldName, beanName, rootClass, errorData, errorMessage, formId, notManually);
    }
}
